package com.hsteach.service.rota;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hsteach.common.core.domain.AjaxResult;
import com.hsteach.common.core.domain.model.AuthInfo;
import com.hsteach.common.exception.ServiceException;
import com.hsteach.common.utils.DateUtils;
import com.hsteach.common.utils.SecurityUtils;
import com.hsteach.common.utils.StringUtils;
import com.hsteach.common.utils.poi.ExcelUtil;
import com.hsteach.dao.domain.rota.Rota;
import com.hsteach.dao.domain.rota.RotaPerson;
import com.hsteach.dao.mapper.rota.RotaMapper;
import com.hsteach.dao.mapper.rota.RotaPersonMapper;
import com.hsteach.enums.BooleanEnum;
import com.hsteach.enums.DutyRoleEnum;
import com.hsteach.framework.feign.client.xgk.dto.ret.GetTeacherRet;
import com.hsteach.service.third.XgkService;
import com.hsteach.web.controller.rota.dto.AddRotaDetailDto;
import com.hsteach.web.controller.rota.dto.AddRotaPersonDto;
import com.hsteach.web.controller.rota.dto.ListRotaDetailDto;
import com.hsteach.web.controller.rota.vo.ListRotaDetailExcel;
import com.hsteach.web.controller.rota.vo.ListRotaDetailVo;
import com.hsteach.web.controller.rota.vo.RotaPersonVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hsteach.dao.mapper.rota.RotaDetailMapper;
import com.hsteach.dao.domain.rota.RotaDetail;
import org.springframework.transaction.annotation.Transactional;

/**
 * 值班日期明细Service业务层处理
 *
 * @author fanxquer
 * @date 2023-10-18
 */
@Service
public class RotaDetailService {
    @Autowired
    private RotaDetailMapper rotaDetailMapper;

    @Autowired
    private RotaPersonMapper rotaPersonMapper;

    @Autowired
    private RotaMapper rotaMapper;

    @Autowired
    private XgkService xgkService;

    /**
     * 查询值班日期明细
     *
     * @param id 值班日期明细主键
     * @return 值班日期明细
     */
    public RotaDetail selectRotaDetailById(Long id) {
        return rotaDetailMapper.selectRotaDetailById(id);
    }

    /**
     * 查询值班日期明细列表
     *
     * @param rotaDetail 值班日期明细
     * @return 值班日期明细
     */
    public List<RotaDetail> selectRotaDetailList(RotaDetail rotaDetail) {
        return rotaDetailMapper.selectRotaDetailList(rotaDetail);
    }

    public AjaxResult importFile(Long id, InputStream is) throws Exception {
        AuthInfo authInfo = SecurityUtils.getAuthInfo();
        ExcelUtil<ListRotaDetailExcel> util = new ExcelUtil<>(ListRotaDetailExcel.class);
        List<ListRotaDetailExcel> excels = util.importExcel("", is, 1);
        List<String> msg = Lists.newArrayList();
        excels = validRows(excels, msg);

        //查询机构所有教职工
        List<GetTeacherRet> teachers = xgkService.getTeachers(SecurityUtils.getAuthInfo().getId());
        // 教职工名字列表
        List<String> teacherNames = teachers.stream().map(GetTeacherRet::getName).collect(Collectors.toList());
        Map<String, List<GetTeacherRet>> groupByName = teachers.stream().collect(Collectors.groupingBy(GetTeacherRet::getName));

        Rota rota = rotaMapper.selectRotaById(id);
        if (rota == null) {
            throw new ServiceException("值班表不存在");
        }
        List<Date> dates = excels.stream().map(ListRotaDetailExcel::getDutyDate).collect(Collectors.toList());
        if (!dates.isEmpty()) {
            rotaDetailMapper.deteleByRotaIdAndDate(id, dates);
        }
//        rotaDetailMapper.deteleByRotaId(id);
        List<RotaPerson> personList = Lists.newArrayList();
        for (int j = 0; j < excels.size(); j++) {
            ListRotaDetailExcel row = excels.get(j);
            if (row.getDutyDate() == null) {
                msg.add("第" + (j+3) + "行，时间为空");
                continue;
            }
            if (rota.getRotaBegin().after(row.getDutyDate()) || rota.getRotaEnd().before(row.getDutyDate())) {
                msg.add("第" + (j+3) + "行，时间处于值班表日期范围外");
                continue;
            }
            if (StringUtils.isNotEmpty(row.getLeaders()) && StringUtils.isNotEmpty(row.getPersons())) {
                String[] leaders = row.getLeaders().split("、");
                String[] persons = row.getPersons().split("、");
                List<String> list = Arrays.asList(leaders).stream().distinct().collect(Collectors.toList());
                list.addAll(Arrays.asList(persons).stream().distinct().collect(Collectors.toList()));
                int size = list.stream().distinct().collect(Collectors.toList()).size();
                if (size < list.size()) {
                    msg.add("第" + (j+3) + "行，值班领导和值班人员有重复");
                    continue;
                }
            }
            RotaDetail detail = new RotaDetail();
            detail.setDutyDate(row.getDutyDate());
            detail.setDelStatus(BooleanEnum.TRUE.getCode());
            detail.setOrgCode(authInfo.getOrgCode());
            detail.setRotaId(id);
            detail.setFileFlg(BooleanEnum.FALSE.getCode());
            detail.setCreateBy(authInfo.getPersonId());
            rotaDetailMapper.insertRotaDetail(detail);
            if (StringUtils.isNotEmpty(row.getLeaders()) && StringUtils.isNotEmpty(row.getLeaderPhones())) {
                String[] leaders = row.getLeaders().split("、");
                String[] leaderPhones = row.getLeaderPhones().split("、");
                if (leaders.length > 10) {
                    msg.add("第" + (j+3) + "行，值班领导超过10人");
                } else if (Arrays.stream(leaders).distinct().collect(Collectors.toList()).size() < leaders.length) {
                    msg.add("第" + (j+3) + "行，值班领导姓名重复");
                } else {
                    for (int i = 0; i < leaders.length; i++) {
                        if (i <= leaderPhones.length) {
                            List<GetTeacherRet> getTeacherRets = groupByName.getOrDefault(leaders[i], Lists.newArrayList());
                            if (getTeacherRets.size() > 1) {
                                // 重名
                                msg.add("第" + (j+3) + "行，值班领导" + leaders[i] + "系统数据有重名");
                                continue;
                            }
                            if (getTeacherRets.size() < 1) {
                                // 未查找到
                                msg.add("第" + (j+3) + "行，值班领导" + leaders[i] + "系统数据中不存在");
                                continue;
                            }
                            if (StringUtils.isNotEmpty(leaderPhones[i]) && leaderPhones[i].length() > 20) {
                                msg.add("第" + (j+3) + "行，电话" + leaderPhones[i] + "长度超过20");
                                continue;
                            }
                            RotaPerson person = new RotaPerson();
                            person.setRotaDetailId(detail.getId());
                            person.setOrgCode(authInfo.getOrgCode());
                            person.setCreateBy(authInfo.getPersonId());
                            person.setRecordFlg(BooleanEnum.FALSE.getCode());
                            person.setPersonId(getTeacherRets.get(0).getPersonId());
                            person.setPersonName(leaders[i]);
                            person.setPersonMobile(leaderPhones[i]);
                            person.setDutyRole(DutyRoleEnum.LEADER.getCode());
                            personList.add(person);
                        }
                    }
                }
            } else if (StringUtils.isNotEmpty(row.getLeaders()) && StringUtils.isEmpty(row.getLeaderPhones())) {
                msg.add("第" + (j+3) + "行，值班领导电话不能为空");
            }

            if (StringUtils.isNotEmpty(row.getPersons()) && StringUtils.isNotEmpty(row.getPersonPhones())) {
                String[] persons = row.getPersons().split("、");
                String[] personPhones = row.getPersonPhones().split("、");
                if (persons.length > 10) {
                    msg.add("第" + (j+3) + "行，值班人员超过10人");
                } else if (Arrays.stream(persons).distinct().collect(Collectors.toList()).size() < persons.length) {
                    msg.add("第" + (j+3) + "行，值班人员姓名重复");
                } else {
                    for (int i = 0; i < persons.length; i++) {
                        if (i <= personPhones.length) {
                            List<GetTeacherRet> getTeacherRets = groupByName.getOrDefault(persons[i], Lists.newArrayList());
                            if (getTeacherRets.size() > 1) {
                                // 重名
                                msg.add("第" + (j+3) + "行，值班人员" + persons[i] + "系统数据有重名");
                                continue;
                            }
                            if (getTeacherRets.size() < 1) {
                                // 未查找到
                                msg.add("第" + (j+3) + "行，值班人员" + persons[i] + "系统数据中不存在");
                                continue;
                            }
                            if (StringUtils.isNotEmpty(personPhones[i]) && personPhones[i].length() > 20) {
                                msg.add("第" + (j+3) + "行，电话" + personPhones[i] + "长度超过20");
                                continue;
                            }
                            RotaPerson person = new RotaPerson();
                            person.setRotaDetailId(detail.getId());
                            person.setOrgCode(authInfo.getOrgCode());
                            person.setCreateBy(authInfo.getPersonId());
                            person.setRecordFlg(BooleanEnum.FALSE.getCode());
                            person.setPersonId(getTeacherRets.get(0).getPersonId());
                            person.setPersonName(persons[i]);
                            person.setPersonMobile(personPhones[i]);
                            person.setDutyRole(DutyRoleEnum.PERSON.getCode());
                            personList.add(person);
                        }
                    }
                }
            }  else if (StringUtils.isNotEmpty(row.getPersons()) && StringUtils.isEmpty(row.getPersonPhones())) {
                msg.add("第" + (j+3) + "行，值班人员电话不能为空");
            }
        }

        if (personList.size() > 0) {
            rotaPersonMapper.batchInsert(personList);
        }

        if (!msg.isEmpty()) {
            throw new ServiceException(String.join("\r\n", msg));
        }
        return AjaxResult.success();
    }

    private List<ListRotaDetailExcel> validRows(List<ListRotaDetailExcel> excels, List<String> msg) {
        List<ListRotaDetailExcel> ret = Lists.newArrayList();
        for (int i = 0; i< excels.size(); i++) {
            ListRotaDetailExcel row = excels.get(i);
            if (row.getDutyDate() == null) {
                msg.add("第" + (i+3) + "行，日期不能为空");
                continue;
            }
//            if (row.getDutyDate() instanceof Date) {
//                msg.add("第" + (i+3) + "行日期格式错误，跳过");
//                continue;
//            }
            if (StringUtils.isEmpty(row.getLeaders()) && StringUtils.isEmpty(row.getPersons())) {
                msg.add("第" + (i+3) + "行，值班领导和人员不能都为空");
                continue;
            }
            if (StringUtils.isNotEmpty(row.getPersonPhones()) && !row.getPersonPhones().replaceAll("、", "").trim().matches("^\\d+$")) {
                msg.add("第" + (i+3) + "行，人员电话格式不正确");
                continue;
            }
            if (StringUtils.isNotEmpty(row.getLeaderPhones()) && !row.getLeaderPhones().replaceAll("、", "").trim().matches("^\\d+$")) {
                msg.add("第" + (i+3) + "行，领导电话格式不正确");
                continue;
            }

            ret.add(row);
        }
        return ret;
    }

    public List<ListRotaDetailVo> selectRotaDetailList(ListRotaDetailDto dto) {
        RotaDetail query = new RotaDetail();
        BeanUtils.copyProperties(dto, query);
        query.setDelStatus(BooleanEnum.TRUE.getCode());
//        query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        List<RotaDetail> rotaDetails = rotaDetailMapper.selectRotaDetailList(query);
        Map<Long, List<RotaPerson>> personMap;
        if (rotaDetails.size() > 0) {
            RotaPerson personQuery = new RotaPerson();
            personQuery.setRotaDetailIds(rotaDetails.stream().map(RotaDetail::getId).collect(Collectors.toList()));
            List<RotaPerson> rotaPeople = rotaPersonMapper.selectRotaPersonList(personQuery);
            personMap = rotaPeople.stream().collect(Collectors.groupingBy(RotaPerson::getRotaDetailId));
        } else {
            personMap = Maps.newHashMap();
        }
        List<ListRotaDetailVo> ret = rotaDetails.stream().map(e -> {
            ListRotaDetailVo vo = new ListRotaDetailVo();
            BeanUtils.copyProperties(e, vo);
            List<RotaPersonVo> personVos = personMap.getOrDefault(e.getId(), Lists.newArrayList())
                    .stream().map(k -> {
                        RotaPersonVo personVo = new RotaPersonVo();
                        BeanUtils.copyProperties(k, personVo);
                        return personVo;
                    }).sorted(Comparator.comparing(RotaPersonVo::getDutyRole)).collect(Collectors.toList());
            vo.setRotaPersons(personVos);
            return vo;
        }).collect(Collectors.toList());
        return ret;
    }

    public List<RotaDetail> listByPersonId(Long rotaId, String personId) {
        RotaDetail query = new RotaDetail();
        query.setRotaId(rotaId);
        query.setDelStatus(BooleanEnum.TRUE.getCode());
        query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        List<RotaDetail> rotaDetails = rotaDetailMapper.selectRotaDetailList(query);
        if (rotaDetails.size() == 0) {
            return Lists.newArrayList();
        }

        List<Long> detailIds = rotaDetails.stream().map(RotaDetail::getId).collect(Collectors.toList());
        RotaPerson personQuery = new RotaPerson();
        personQuery.setRotaDetailIds(detailIds);
        Set<Long> fIds = rotaPersonMapper.selectRotaPersonList(personQuery).stream().filter(e -> personId.equals(e.getPersonId()))
                .map(RotaPerson::getRotaDetailId).collect(Collectors.toSet());

        return rotaDetails.stream().filter(e -> fIds.contains(e.getId())).collect(Collectors.toList());
    }

    public List<RotaDetail> listByPersonIdAndMNotMe(Long rotaId, String personId, String me) {
        RotaDetail query = new RotaDetail();
        query.setRotaId(rotaId);
        query.setDelStatus(BooleanEnum.TRUE.getCode());
        query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        List<RotaDetail> rotaDetails = rotaDetailMapper.selectRotaDetailList(query);
        if (rotaDetails.size() == 0) {
            return Lists.newArrayList();
        }

        List<Long> detailIds = rotaDetails.stream().map(RotaDetail::getId).collect(Collectors.toList());
        RotaPerson personQuery = new RotaPerson();
        personQuery.setRotaDetailIds(detailIds);
        List<RotaPerson> rotaPeople = rotaPersonMapper.selectRotaPersonList(personQuery);
        Set<Long> fIds = rotaPeople.stream().filter(e -> personId.equals(e.getPersonId()))
                .map(RotaPerson::getRotaDetailId).collect(Collectors.toSet());
        Set<Long> meIds = rotaPeople.stream().filter(e -> me.equals(e.getPersonId()))
                .map(RotaPerson::getRotaDetailId).collect(Collectors.toSet());

        return rotaDetails.stream().filter(e -> fIds.contains(e.getId()) && !meIds.contains(e.getId())).collect(Collectors.toList());
    }

    /**
     * 新增值班日期明细
     *
     * @param rotaDetail 值班日期明细
     * @return 结果
     */
    public int insertRotaDetail(RotaDetail rotaDetail) {
        rotaDetail.setCreateTime(DateUtils.getNowDate());
        return rotaDetailMapper.insertRotaDetail(rotaDetail);
    }

    @Transactional(rollbackFor = Exception.class)
    public int addRotaDetail(AddRotaDetailDto dto) {
        RotaDetail query = new RotaDetail();
        query.setDelStatus(BooleanEnum.TRUE.getCode());
        query.setRotaId(dto.getRotaId());
        query.setDutyDate(dto.getDutyDate());
        List<RotaDetail> rotaDetails = rotaDetailMapper.selectRotaDetailList(query);
        if (rotaDetails.size() > 0) {
            throw new ServiceException("该日期已有值班人员，新增失败");
        }
        RotaDetail detail = new RotaDetail();
        BeanUtils.copyProperties(dto, detail);
        detail.setDelStatus(BooleanEnum.TRUE.getCode());
        detail.setCreateBy(SecurityUtils.getAuthInfo().getPersonId());
        detail.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        int i = rotaDetailMapper.insertRotaDetail(detail);
        if (i <= 0) {
            throw new ServiceException("新增失败");
        }
        return 0;
    }

    @Transactional(rollbackFor = Exception.class)
    public int addRotaPerson(AddRotaPersonDto dto) {
        if (dto.getPersonMobile().length() > 20) {
            throw new ServiceException("电话号码长度不能超过20");
        }

        Rota rota = rotaMapper.selectRotaById(dto.getRotaId());
        if (rota == null) {
            throw new ServiceException("值班表不存在");
        }
        if (rota.getRotaBegin().after(dto.getDutyDate()) || rota.getRotaEnd().before(dto.getDutyDate())) {
            throw new ServiceException("值班表日期范围外无法增加值班人员");
        }

        RotaDetail query = new RotaDetail();
        query.setDelStatus(BooleanEnum.TRUE.getCode());
        query.setRotaId(dto.getRotaId());
        query.setDutyDate(dto.getDutyDate());
        List<RotaDetail> rotaDetails = rotaDetailMapper.selectRotaDetailList(query);
        if (rotaDetails.size() <= 0) {
            query.setFileFlg(BooleanEnum.FALSE.getCode());
            query.setCreateBy(SecurityUtils.getAuthInfo().getPersonId());
            query.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
            query.setCreateBy(SecurityUtils.getAuthInfo().getPersonId());
            rotaDetailMapper.insertRotaDetail(query);
        } else {
            query = rotaDetails.get(0);
        }

        RotaPerson personQuery = new RotaPerson();
        personQuery.setRotaDetailId(query.getId());
        personQuery.setPersonId(dto.getPersonId());
        List<RotaPerson> rotaPeople = rotaPersonMapper.selectRotaPersonList(personQuery);
        if (rotaPeople.size() > 0) {
            throw new ServiceException("该值班人员已存在，添加失败");
        }

        personQuery.setDutyRole(dto.getDutyRole());
        personQuery.setPersonId(null);
        List<RotaPerson> rotaPeople1 = rotaPersonMapper.selectRotaPersonList(personQuery);
        if (rotaPeople1.size() >= 10) {
            throw new ServiceException("该值班角色人数当天不能超过10人");
        }

        personQuery.setPersonName(dto.getPersonName());
        personQuery.setPersonId(dto.getPersonId());
        personQuery.setPersonMobile(dto.getPersonMobile());
        personQuery.setDutyRole(dto.getDutyRole());
        personQuery.setOrgCode(SecurityUtils.getAuthInfo().getOrgCode());
        personQuery.setCreateBy(SecurityUtils.getAuthInfo().getPersonId());
        personQuery.setRecordFlg(BooleanEnum.FALSE.getCode());
        int i = rotaPersonMapper.insertRotaPerson(personQuery);

        return i;
    }

    public int removePerson(Long id) {
        return rotaPersonMapper.deleteRotaPersonById(id);
    }

    /**
     * 修改值班日期明细
     *
     * @param rotaDetail 值班日期明细
     * @return 结果
     */
    public int updateRotaDetail(RotaDetail rotaDetail) {
        rotaDetail.setUpdateTime(DateUtils.getNowDate());
        return rotaDetailMapper.updateRotaDetail(rotaDetail);
    }

    public int updateByRotaId(RotaDetail rotaDetail) {
        rotaDetail.setUpdateTime(DateUtils.getNowDate());
        return rotaDetailMapper.updateByRotaId(rotaDetail);
    }

    /**
     * 批量删除值班日期明细
     *
     * @param ids 需要删除的值班日期明细主键
     * @return 结果
     */
    public int deleteRotaDetailByIds(Long[] ids) {
        return rotaDetailMapper.deleteRotaDetailByIds(ids);
    }

    /**
     * 删除值班日期明细信息
     *
     * @param id 值班日期明细主键
     * @return 结果
     */
    public int deleteRotaDetailById(Long id) {
        return rotaDetailMapper.deleteRotaDetailById(id);
    }
}
